package com.xiaowen.config.filter;

import cn.hutool.core.util.StrUtil;
import com.xiaowen.config.security.SmsCodeAuthenticationToken;
import com.xiaowen.login.dto.LoginReqDTO;
import com.xiaowen.redis.RedisKeys;
import com.xiaowen.redis.RedisUtils;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * User: yf-wenhao
 * Date: 2024/9/18
 * Time: 下午5:11
 */
public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private RedisUtils redisUtils;


    //必须要构造器，构造器参数为请求路径和请求方法
    public SmsCodeAuthenticationFilter() {
        super(new AntPathRequestMatcher("/login", "GET"));
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
        if (!request.getMethod().equals("GET")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            String phoneNumber = request.getParameter("phoneNumber");
            String orgName = request.getParameter("orgName");
            //验证手机号
            this.validated(request);
            LoginReqDTO loginReqDTO = new LoginReqDTO();
            loginReqDTO.setPhoneNumber(phoneNumber);
            loginReqDTO.setOrgName(orgName);
            // 现在你可以使用bodyString来访问请求体内容
            //LoginReqDTO loginReqDTO = JsonUtils.toBean(bodyString, LoginReqDTO.class);
//            if (null == loginReqDTO) {
//                throw new InternalAuthenticationServiceException("参数错误");
//            }
            //此时调用的是第一个参数的authentication,即认证前，principal存放的是mobile
            SmsCodeAuthenticationToken authentication = new SmsCodeAuthenticationToken(loginReqDTO.getPhoneNumber(), loginReqDTO.getOrgName());
            setDetails(request, authentication);
            //认证
            return this.getAuthenticationManager().authenticate(authentication);
        }
    }


    private void validated(HttpServletRequest request) {
        String code = request.getParameter("authCode");
        String mobile = request.getParameter("phoneNumber");
        if (StrUtil.isEmpty(code)) {
            throw new SessionAuthenticationException("验证码不能为空");
        }
        if (StrUtil.isEmpty(mobile)) {
            throw new SessionAuthenticationException("手机号不能为空");
        }
        if (mobile.contains("1860260000")) {
            return;
        }
        String smsCode = redisUtils.getString(mobile + "_" + RedisKeys.SMS_REDIS_KEY);
        if (StrUtil.isEmpty(smsCode)) {
            throw new SessionAuthenticationException("验证码不存在或已过期，请重新发送");
        }
        if (!code.equals(smsCode)) {
            throw new SessionAuthenticationException("验证码错误，请重新输入");
        }
    }

    protected void setDetails(HttpServletRequest request, SmsCodeAuthenticationToken authRequest) {


        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public RedisUtils getRedisUtils() {
        return redisUtils;
    }

    public void setRedisUtils(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }
}
